(define-module (display-utils))


(use-modules
 ;; SRFI-69 for hash tables
 (srfi srfi-69)
 (model))


(define-public displayln
  (lambda* (#:key (output-port (current-output-port)) (verbose #t) . msgs)
    (when verbose
      (display (string-append
                (string-join
                 (map (lambda (msg) (simple-format #f "~a" msg)) msgs)
                 " ") "\n")
               output-port))))


;; alias for displayln
(define-public debug displayln)


(define-public format-fraction
  (lambda* (fraction #:key (precision 5))
    (format #f
            (string-append "~"
                           (number->string (+ precision 2))
                           ","
                           (number->string precision)
                           "f")
            fraction)))


(define-public format-fight-situation
  (λ (fight-situation)
    (call-with-output-string
      (λ (output-port)
        (display
         (simple-format
          #f
          "A wins: ~a, A remaining: ~a, D wins: ~a, D remaining: ~a"
          (get-att-wins fight-situation)
          (get-att-rems fight-situation)
          (get-def-wins fight-situation)
          (get-def-rems fight-situation))
         output-port)))))


(define-public display-probability-and-fight-situation
  (lambda* (prob
            fight-situation
            #:key
            (fraction-formatter format-fraction))
    (displayln
     (string-append "probability "
                    (fraction-formatter prob)
                    ": "
                    (format-fight-situation fight-situation)))))


(define-public display-summary
  (lambda* (summary-table
            #:key
            (fraction-formatter format-fraction))
    (let ([number-of-results (apply + (hash-table-values summary-table))])
      (let ([sorted-summary-table
             (sort (hash-table->alist summary-table)
                   ;; compare wins λ
                   (λ (res-and-count1 res-and-count2)
                     (fight-situation-less-than
                      (list->fight-situation (car res-and-count1))
                      (list->fight-situation (car res-and-count2)))))])
        (for-each
         (λ (res-and-count)
           (let ([fight-result (list->fight-situation (car res-and-count))]
                 [count (cdr res-and-count)])
             (display-probability-and-fight-situation
              (/ count number-of-results)
              fight-result
              #:fraction-formatter fraction-formatter)))
         sorted-summary-table)))))
